Objectifs de la séance :
"""texte""").L = [1, 2, 3], méthodes append, pop.d = {"a": 1, "b": 2}.s = {1, 2, 3}, opérations ensemblistes.x = 5
if x > 0:
print("positif")
elif x == 0:
print("zéro")
else:
print("négatif")
En Python, une classe est un modèle qui permet de créer des objets regroupant à la fois données (attributs) et comportements (méthodes).
Exemple : un rectangle représenté par sa largeur et sa hauteur.
Rectangle avec largeur, hauteur, et des méthodes qui calculent l’aire ou le périmètre.__init__.self.class Rectangle:
def __init__(self, largeur, hauteur):
self.largeur = largeur # attribut
self.hauteur = hauteur # attribut
def aire(self):
return self.largeur * self.hauteur # méthode
Points à expliquer
self représente l’objet courant.largeur et hauteur.r = Rectangle(3, 4)
print(r.aire()) # 12
Boucles :
for i in range(5):
print(i)
while x > 0:
x -= 1
Fonction :
def factorielle(n):
if n == 0:
return 1
return n * factorielle(n-1)
__init__ (10 min)__init__ est une méthode spéciale appelée automatiquement lors de la création de l’objet.return, elle renvoie implicitement l’objet construit.Expliquer que __init__ n’est pas obligatoire : si on ne le définit pas, Python crée un constructeur par défaut sans paramètres.
Certaines méthodes commencent et finissent par __. Elles définissent comment l’objet se comporte dans des situations particulières.
__str__ : ce qui est affiché quand on fait print(objet). Permet un rendu lisible.__repr__ (parent de __str__) : version plus technique, utilisée en debug.__add__ : ce qui se passe quand on écrit objet1 + objet2.Exemple :
class Rectangle:
def __init__(self, largeur, hauteur):
self.largeur = largeur
self.hauteur = hauteur
def __str__(self):
return f"Rectangle({self.largeur}x{self.hauteur})"
def __add__(self, autre):
return Rectangle(self.largeur + autre.largeur,
self.hauteur + autre.hauteur)
r1 = Rectangle(3, 4)
r2 = Rectangle(2, 5)
print(r1) # Rectangle(3x4)
print(r1 + r2) # Rectangle(5x9)
Message clé :
Ces méthodes spéciales permettent de rendre nos objets naturels à utiliser.
Exemple parallèle : les entiers en Python utilisent en interne leur propre __add__, __str__, etc.
@property (20 min)Problème : parfois une valeur doit être calculée à la volée, mais on aimerait y accéder comme un attribut.
Solution : @property.
class Rectangle:
def __init__(self, largeur, hauteur):
self.largeur = largeur
self.hauteur = hauteur
@property
def ratio(self):
return self.largeur / self.hauteur
On écrit r.ratio au lieu de r.ratio().
Bonus : protection en écriture de l’attribut.
On peut protéger un attribut pour qu’il ne soit pas modifié directement.
Exemple : la valeur de l’aire dépend de largeur et hauteur. On ne veut pas que l’utilisateur fasse r.aire = 10.
r = Rectangle(3, 4)
r.aire = 10 # erreur, car pas défini en écriture
Créer des classes répétitives avec juste des attributs et un __init__ devient verbeux.
Le module dataclasses introduit un décorateur @dataclass qui génère automatiquement :
__init____repr____eq__ (comparaison)Exemple :
from dataclasses import dataclass
@dataclass
class SerieTelevisee:
duree_episode: float
n_episodes: int
n_saisons: int
categorie: str
def __post_init__(self):
self.duree_total = self.duree_episode * self.n_episodes * self.n_saisons
Points à dire
__post_init__ est appelé après __init__ généré automatiquement.duree_total).Montrer la conversion entre :
Exemple donné aux étudiants :
# Version procédurale
def duree_totale(duree_episode, n_episodes, n_saisons):
return duree_episode * n_episodes * n_saisons
series = [
{"titre": "Dark", "duree_episode": 50, "n_episodes": 10, "n_saisons": 3, "categorie": "SF"},
{"titre": "The Office", "duree_episode": 22, "n_episodes": 24, "n_saisons": 9, "categorie": "Comédie"}
]
for s in series:
print(s["titre"], duree_totale(s["duree_episode"], s["n_episodes"], s["n_saisons"]))
Activité
SerieTelevisee. »Message clé